namespace NHibernate.Sidekick.Data.NHibernate
{
    /// <summary>
    /// Provides an abstract interface for the specified type.
    /// </summary>
    /// <typeparam name="T">The specified type.</typeparam>
    /// <typeparam name="TId">The type of the id.</typeparam>
    public interface IDao<T, TId>
    {
        /// <summary>
        /// Persist the given transient instance, first assigning a generated identifier.
        /// </summary>
        /// <param name="entity">The transient entity.</param>
        /// <returns>The saved instance.</returns>
        TId Save(T entity);

        /// <summary>
        /// Update the persistent instance with the identifier of the given detached instance.
        /// </summary>
        /// <param name="entity">The transient entity.</param>
        /// <returns>The updated instance.</returns>
        void Update(T entity);

        /// <summary>
        /// Either <see cref="Save(T)"/> or <see cref="Update(T)"/> the given instance, depending upon resolution of the unsaved-value checks
        /// </summary>
        /// <param name="entity">A transient or detached instance containing new or updated state .</param>
        /// <returns></returns>
        void SaveOrUpdate(T entity);

        /// <summary>
        /// Copy the state of the given object onto the persistent object with the same identifier. 
        /// If there is no persistent instance currently associated with the session, it will be loaded. 
        /// Return the persistent instance. If the given instance is unsaved or does not exist in the database, 
        /// save it and return it as a newly persistent instance. Otherwise, the given instance does not become 
        /// associated with the session.
        /// </summary>
        TId SaveOrUpdateCopy(T entity);

        /// <summary>
        /// Remove a persistent instance from the datastore. The argument may be an instance associated
        /// with the receiving Session or a transient instance with an identifier associated with existing
        /// persistent state. This operation cascades to associated instances if the association is mapped
        /// with cascade="delete". 
        /// </summary>
        /// <param name="entity">The instance to be removed.</param>
        void Delete(T entity);

        /// <summary>
        /// Remove a persistent instance from the datastore. The argument may be an instance associated
        /// with the receiving Session or a transient instance with an identifier associated with existing
        /// persistent state. This operation cascades to associated instances if the association is mapped
        /// with cascade="delete". 
        /// </summary>
        /// <param name="id">The instance's identifier.</param>
        void Delete(TId id);

        /// <summary>
        /// Flush the associated ISession and end the unit of work.
        /// </summary>
        void CommitChanges();

        /// <summary>
        /// Forces the underlying <see cref="ITransaction"/> to roll back.
        /// </summary>
        void RollBackChanges();

        /// <summary>
        /// Re-read the state of the given instance from the underlying database.
        /// </summary>
        /// <param name="entity">The persistent instance.</param>
        void Refresh(T entity);
    }
}
